package com.ocom.ugcapi.util;


import com.ocom.common.utils.KeyUtils;
import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.*;
import java.util.Base64;


public class Sm2Utils {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 根据publicKey对原始数据data，使用SM2加密
     *
     * @param data
     * @param publicKey
     * @return
     */
    public static byte[] encrypt(byte[] data, PublicKey publicKey) {
        ECPublicKeyParameters localECPublicKeyParameters = null;

        if (publicKey instanceof BCECPublicKey) {
            BCECPublicKey localECPublicKey = (BCECPublicKey) publicKey;
            ECParameterSpec localECParameterSpec = localECPublicKey.getParameters();
            ECDomainParameters localECDomainParameters = new ECDomainParameters(localECParameterSpec.getCurve(),
                    localECParameterSpec.getG(), localECParameterSpec.getN());
            localECPublicKeyParameters = new ECPublicKeyParameters(localECPublicKey.getQ(), localECDomainParameters);
        }
        SM2Engine localSM2Engine = new SM2Engine();
        localSM2Engine.init(true, new ParametersWithRandom(localECPublicKeyParameters, new SecureRandom()));
        byte[] arrayOfByte2;
        try {
            arrayOfByte2 = localSM2Engine.processBlock(data, 0, data.length);
            return arrayOfByte2;
        } catch (InvalidCipherTextException e) {

            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据privateKey对加密数据encodedata，使用SM2解密
     *
     * @param encodedata
     * @param privateKey
     * @return
     */
    public static byte[] decrypt(byte[] encodedata, PrivateKey privateKey) {
        SM2Engine localSM2Engine = new SM2Engine();
        BCECPrivateKey sm2PriK = (BCECPrivateKey) privateKey;
        ECParameterSpec localECParameterSpec = sm2PriK.getParameters();
        ECDomainParameters localECDomainParameters = new ECDomainParameters(localECParameterSpec.getCurve(),
                localECParameterSpec.getG(), localECParameterSpec.getN());
        ECPrivateKeyParameters localECPrivateKeyParameters = new ECPrivateKeyParameters(sm2PriK.getD(),
                localECDomainParameters);
        localSM2Engine.init(false, localECPrivateKeyParameters);
        try {
            byte[] arrayOfByte3 = localSM2Engine.processBlock(encodedata, 0, encodedata.length);
            return arrayOfByte3;
        } catch (InvalidCipherTextException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 私钥签名
     *
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] signByPrivateKey(byte[] data, PrivateKey privateKey) throws Exception {
        Signature sig = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), BouncyCastleProvider.PROVIDER_NAME);
        sig.initSign(privateKey);
        sig.update(data);
        byte[] ret = sig.sign();
        return ret;
    }

    /**
     * 公钥验签
     *
     * @param data
     * @param publicKey
     * @param signature
     * @return
     * @throws Exception
     */
    public static boolean verifyByPublicKey(byte[] data, PublicKey publicKey, byte[] signature) throws Exception {
        Signature sig = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), BouncyCastleProvider.PROVIDER_NAME);
        sig.initVerify(publicKey);
        sig.update(data);
        boolean ret = sig.verify(signature);
        return ret;
    }


    public static void main(String[] args) throws UnsupportedEncodingException {
        String privateKey1 ="MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgXY0TIoadv7XHvwg6OR7+463Bp/o2SxF4SKxHa78tVBmgCgYIKoEcz1UBgi2hRANCAATHLKr2LMIErBjtVeJlwR77xsugUtdkA5ZSghuO4hDRvILY/WeMiA7Tszf9G6zkapIHetDVHXQYLGHSSyTqg8zu";

        System.out.println(getSm2Decry("BJM6vi70LI9mF0qUOHxueeZiaPZlgrInpZ4bGw1KO09Po/tWtl6rNrByk8+P0G3OnPSduKQleY4v+tSQQLqJVN4Kckfv4CUdQ9MwJteEG1d76tXcU3WcX9yakKkvsdZSM3iU6HegGSv5EN97uULTbeE=",privateKey1));

        if(true){
            return;
        }

        String privateKey ="MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgX5l7kx8YzBFlVw7yqdL2+CK+kqa0x35lj1c8ehEJE86gCgYIKoEcz1UBgi2hRANCAASFbflG4QLXu5dL6KCG1gp8jqcCpyChywIHK2lnQhV+B8w9MORX14z2h3eTJ6fWcGaqARyJnjqKOPegoOYB3HJy";
        String PublicKey =  "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEhW35RuEC17uXS+ightYKfI6nAqcgocsCBytpZ0IVfgfMPTDkV9eM9od3kyen1nBmqgEciZ46ijj3oKDmAdxycg==";
    //    String testStr = "13839327852&6532457825";
        String testStr = "{\"userId\":\"123456\",\"timestamp\":\"123456\"}";
        byte[] encrypt =	 Sm2Utils.encrypt(testStr.getBytes(), KeyUtils.createPublicKey(PublicKey));
        System.out.println(encrypt);
        String encryptBase64Str =	 Base64.getEncoder().encodeToString(encrypt);
        System.out.println("加密数据：" + encryptBase64Str);

        String encryptUrlEncode = URLEncoder.encode(encryptBase64Str,"utf-8"); ;

        System.out.println("加密数据URLENCODE：" + encryptUrlEncode);

        encryptBase64Str =  "BCHzAM3puNI3e0rdNc0CDdze8cE0sJS8ZiJ%2BJrgnq5xVJbP3xw5zhQSkzbaitbyoijnajWkZKJ79bSML62SGNasszRt5eQdeS5QamQcXMQgt0mOjE%2FgRGWOo%2FSM%2BFeImr7QhT0Z20wZ0lsS0hLbJ5k5FHJqD3ZHL8eLUv7AO7De3PPJjCzaGFHQ%3D";

//        String encryptUrlDecode = URLDecoder.decode(encryptBase64Str,"utf-8"); ; ;
//
//        byte[] decode =	 Base64.getDecoder().decode(encryptUrlDecode);
//
//        byte[] decrypt =	 Sm2Utils.decrypt(decode, KeyUtils.createPrivateKey(privateKey));
//        System.out.println("解密数据：" + new String(decrypt));

        String encryptUrlDecode = "BKUzl6ZlHUrXwNWfhGLru49iFSl/tD70K49+4gg8if0wfADQx+3QSnZyMV74LmnrB8fdMjhasyreG0PkSOgV3nU69m4mcRq+BPT1J+jxXkJrC/hppKWqvGq8ByaGkROC64tryONVGXkeNyTlfnhW1b/9kvLd836N5Hk8pmR5FbyQpEjV+4W9H70cHvS8VE2SVMMm7zT7f7iMeD9EZuX1" ;

        System.out.println(   URLEncoder.encode(encryptUrlDecode,"utf-8")); ;


        byte[] decode =	 Base64.getDecoder().decode(encryptUrlDecode);

        byte[] decrypt =	 Sm2Utils.decrypt(decode, KeyUtils.createPrivateKey(privateKey));
        System.out.println("解密数据：" + new String(decrypt));
        System.out.println("解密数据2：" + testStr);


    }



    public static String getSm2Encry(String encStr,String pubKey){
        try {
            byte[] encryp =  Sm2Utils.encrypt(encStr.getBytes(), KeyUtils.createPublicKey(pubKey));
            String encryptBase64Str =Base64.getEncoder().encodeToString(encryp);
            return URLEncoder.encode(encryptBase64Str,"utf-8");
        }catch (Exception exception){
            return "";
        }
    }

    public static String getSm2Decry(String decStr,String priKey){
        try {
            String dec = URLDecoder.decode(decStr,"utf-8");
            byte[] deBase64Str =Base64.getDecoder().decode(dec);
            byte[] by =  Sm2Utils.decrypt(deBase64Str,KeyUtils.createPrivateKey(priKey));
            return new String(by);
        }catch (Exception exception){
            exception.printStackTrace();
            return "";
        }

    }



}
